<!--
 * @Descripttion: 
 * @Version: 
 * @Author: gaohj
 * @Date: 2022-12-28 15:11:49
 * @LastEditors: Please set LastEditors
 * @LastEditTime: 2022-12-28 16:29:55
-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        // 函数分为两个阶段
        // 1. 定义阶段
            // 声明式   定义以前调用  定义以后调用 都可以 

            // 赋值式   只能定义以后调用 不能定义以前调用
        // 2. 调用阶段

        // alert(add(10,20));
        function add(a,b){
            return a+b;
        }
        // alert(add(10,20));

        // alert(add1(10,20)); // 报错 
        var add1 = function(a,b){
            return a+b;
        }
        // alert(add1(10,20)); //赋值式的函数 只能定义以后调用




        // 为什么声明式的函数可以定义以前调用 定义以后调用
        // 而赋值式的函数只能定义以后调用?


        // 函数的预解析来解释 

        //  console.log(num); // undefined
        //  var num = 10; // 预解析
        //  console.log(num);// 10 


        //  // 等价于 

        //  var num;
        //  console.log(num); // undefined
        //  num = 10;
        //  console.log(num);// 10



        //  fn();
        //  function fn(){
        //     console.log("我是函数");
        //  }
        //  fn();

         // 打开浏览器 
         // 1.fn()
         // 2. function fn(){ console.log("我是函数"); }
         // 3. fn();

         // 预解析 
         // 1. 不需要
         // 2. 需要 声明一个fn的变量 并且赋值为一个函数 
         // 3. 不需要

        // 执行阶段
        // 1. 正常调用 
        // 预解析阶段 已经完成了声明 并且里边是个函数 
        // 2. fn(); 跟上面 一样 正常调用  


        // 等价于 
        // function fn(){ console.log("我是函数"); }
        // fn();
        // fn();


        //赋值式的函数 

        // fn2();
        // var fn2 = function(){
        //     console.log("我是赋值式的函数");
        // }
        // fn2();

        // 打开浏览器
        // 1. fn2();
        // 2. var fn2 = function(){ console.log("我是赋值式的函数"); }
        // 3. fn2();


        // 预解析 
        // 1. 不需要
        // 2. 需要 声明一个fn2的变量 但是不赋值 
        // 3. 不需要


        // 执行 

        // 1. fn2(); 
        // 预解析阶段 fn2仅仅是 声明了一个变量 但是没有赋值
        // 此时fn2是一个undefined 我们fn2() 加了一个括号
        // 当成函数来调用   结果是 fn2 is not a function 
        // 2. 将一个函数赋值给fn2 fn2此时变成了一个函数
        // 3. fn2(); fn2里边是一个函数 
        /// fn2()当做一个函数来调用
        // 正常调用  


        function fn3(){
            var num = 100;
            console.log(num);
            
        }
        fn3();

        // 预解析 
        // 1. 需要 声明一个fn3的变量 并且赋值为一个函数
        // 2. 不需要


        // 执行阶段 
        // fn3(); 
        // 预解析阶段 fn3已经声明了 并且里边是一个函数
        // 当做函数正常调用 

            // 开始对函数内的代码进行预解析
            // 1.声明变量 但是不赋值 


            // 函数内代码预解析完成 然后执行 
            // 1. 把100 赋值给num
            // 2. 打印num


            

    </script>
</body>
</html>